package com.sise.service.impl;


import com.sise.dto.FilterWordDTO;
import com.sise.dto.RpcRespDTO;
import com.sise.dto.TextDetectionDTO;
import com.sise.model.StringItem;
import com.sise.model.StringWordNode;
import com.sise.service.FilterService;
import com.sise.service.FilterWordLogService;
import io.netty.util.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.NavigableSet;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.sise.model.StringItem.countHash;


/**
 * @author idea
 * @data 2019/6/5
 */
@Service(value = "ugcWordFilter")
public class UgcCoreFilterImpl implements FilterService {

    @Autowired
    private TextDetectionServiceImpl textDetectionService;

    @Autowired
    private FilterWordLogService filterWordLogService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private SensitiveWordServiceImpl sensitiveWordService = new SensitiveWordServiceImpl();

    /**
     * DFA数组的长度
     */
    private static final int DEFAULT_LENGTH = 131072;

    /**
     * 默认全文匹配的步长
     */
    private static final int DEFAULT_STEP=2;

    /**
     * 敏感指标参数
     */
    private int sensitiveLevel = 0;


    public static final StringWordNode[] STRING_WORD_NODES = new StringWordNode[DEFAULT_LENGTH];


    public static boolean put(String word) {
        if (word == null || word.length() < 2) {
            return false;
        }
        StringItem item = new StringItem(word);
        String key = word.substring(0, 2);
        int hash = countHash(key);
        //拿到桶数组的index指标
        int index = hash & (STRING_WORD_NODES.length - 1);
        int prefixHash = item.countTwoCharHash(0);
        StringWordNode node = new StringWordNode(prefixHash);

        StringWordNode bucketItem = STRING_WORD_NODES[index];
        synchronized (UgcCoreFilterImpl.class) {
            if (bucketItem != null) {
                for (; bucketItem != null; bucketItem = bucketItem.next) {
                    if (bucketItem.headCharHash == prefixHash) {
                        bucketItem.treeSet.add(item);
                        return true;
                    }
                    if (bucketItem.next == null) {
                        new StringWordNode(prefixHash, bucketItem).treeSet.add(item);
                        return true;
                    }
                }
            } else {
                node.treeSet.add(item);
                STRING_WORD_NODES[index] = node;
            }
        }
        return true;
    }

    @Override
    public  RpcRespDTO<String> filter(FilterWordDTO filterWordDTO) {
        if (filterWordDTO == null || filterWordDTO.getContent() == null) {
            return new RpcRespDTO<String>().buildErrorParamResp(null);
        }
        String content = filterWordDTO.getContent();
        //过滤掉特殊的非法字符，统一为小写
        String word = specialWordFilter(content);
        boolean isSensitive = false;
        List<String> wordList = new ArrayList<>();
        List<String> sensitiveWordList = sensitiveWordService.sensitiveWordFilterByStep(word,DEFAULT_STEP);
        System.out.println("this is wordlist");
        if (!CollectionUtils.isEmpty(sensitiveWordList)) {
            for (String matchWord : sensitiveWordList) {
                StringItem stringItem = new StringItem(matchWord);
                //关键字过滤核心
                int hash = countHash(matchWord);
                int arrIndex = hash & (STRING_WORD_NODES.length - 1);
                StringWordNode node = STRING_WORD_NODES[arrIndex];
                //匹配到位的节点
                if (node != null) {
                    //todo
                    int prefixHash = stringItem.countTwoCharHash(0);

                    for (; node != null; node = node.next) {
                        if (node.headCharHash == prefixHash) {
                            //这里已经出现敏感词命中的情况了(这里的长度不会很长)
                            TreeSet<StringItem> treeSet = node.treeSet;

                            NavigableSet<StringItem> desSet = treeSet.descendingSet();
                            for (StringItem item : desSet) {
                                if (item.getWord().contains(matchWord)) {
                                    System.out.println("出现不合理词汇！:" + matchWord);
                                    sensitiveLevel++;
                                    isSensitive = true;
                                    wordList.add(matchWord);
                                }
                            }

                        }
                    }
                }
            }

            filterWordLogService.save(filterWordDTO);
            if (isSensitive) {
                TextDetectionDTO textDetectionDTO = new TextDetectionDTO();
                textDetectionDTO.setCheckContent(content);
                textDetectionDTO.setSensitiveLevel(sensitiveLevel);
                textDetectionDTO.setSensitiveWordArr(buildSensitiveWordArr(wordList));
                textDetectionService.saveOne(textDetectionDTO);
            }
        }
        return new RpcRespDTO<String>().buildSuccessResp(word);
    }


    /**
     * 特殊字符净化器(将非正常字符进行过滤)
     *
     * @param word 待过滤文本
     * @return
     */
    private String specialWordFilter(String word) {
        //英文字符+中文字符
        String regEx = "[`~!@#$%^&*()+=|{}\\-_':;',\\[\\].<>/?" + "~！@#￥%……&*（）——+|{}-【】‘；：”“’。，、？]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(word);
        return m.replaceAll("").trim().toLowerCase();
    }


    /**
     * 构建敏感词汇信息
     *
     * @param wordList 敏感词汇List
     * @return
     */
    private String buildSensitiveWordArr(List<String> wordList) {
        if (CollectionUtils.isEmpty(wordList)) {
            return StringUtil.EMPTY_STRING;
        } else {
            if (wordList.size() == 1) {
                return wordList.get(0);
            } else {
                StringBuilder stb = new StringBuilder();
                int index = 0;
                for (String word : wordList) {
                    if (index == wordList.size()) {
                        stb = stb.append(word);
                    } else {
                        stb = stb.append(word + ",");
                    }
                    index++;
                }
                return stb.toString();
            }
        }
    }

    /**
     * 过滤英文单词
     *
     * @return
     */
    private String filterEnglishWord(String word){
        return null;
    }


}
